package it.uni.bo.monitoring.protocol.unmarshaller.analysis;

import static it.uni.bo.monitoring.service.StaticFields.CONTENT_MIN_SIZE;
import static it.uni.bo.monitoring.service.StaticFields.FAILB;
import static it.uni.bo.monitoring.service.StaticFields.FAIL_DESC_B;
import static it.uni.bo.monitoring.service.StaticFields.INB;
import static it.uni.bo.monitoring.service.StaticFields.KEY_SIZE;
import static it.uni.bo.monitoring.service.StaticFields.NUM_PAR_B;
import static it.uni.bo.monitoring.service.StaticFields.OUTB;
import static it.uni.bo.monitoring.service.StaticFields.PAR_B;
import static it.uni.bo.monitoring.service.StaticFields.SESS_B;
import static it.uni.bo.monitoring.service.StaticFields.TIME_B;

import it.uni.bo.monitoring.protocol.server.DataObject;
import it.uni.bo.monitoring.protocol.unmarshaller.EventInfo;

import java.nio.ByteBuffer;

import org.apache.log4j.Logger;


public class SizeControl implements Validation {

	private static final String ERROR_SIZE="dimensione del pacchetto non corretta (chiave o content troppo piccolo)";
	private static final String ERROR_SIZE2="dimensione del pacchetto troppo piccola";
	private static final String ERROR_SIZE_KEY="dimensione della chiave Inbound troppo piccola";
	private static final String ERROR_SIZE_PAR="dimensione dei parametri non corretta";
	private static final String ERROR_SIZE_FIELD="alcuni campi sono vuoti (username, password, sequence number...)";
	private static final String ERROR_FORMAT_TIMESTAMP="conversione timestamp";
	private static final String ERROR_SIZE_FIELD2="dimensione timestamp o sessione non corretta";
	private Logger l;
	
	public SizeControl(){
		l = Logger.getLogger(this.getClass());
	}
	
	public boolean validate(EventInfo ei) {
		boolean ok=	packetSize(ei) &&
					fieldsSize(ei);
		
		//l.info("SizeControl: "+ok);
		return ok;
	}
	
	private boolean packetSize(EventInfo ei){
		int minSize=KEY_SIZE;
		byte[] key=ei.getIdE();
		int size=ei.getSize();
		DataObject rdo=ei.getDataObject();
		if((key.length!=KEY_SIZE) || (size!=key.length+rdo.getContent().length)){
			l.error(ERROR_SIZE);
			return false;
		}

		byte direction= rdo.getDirection();
		if(direction == INB)
			minSize+=CONTENT_MIN_SIZE;
		else if(direction == OUTB)
			minSize+=KEY_SIZE + CONTENT_MIN_SIZE;
		else if(direction == FAILB)
			minSize+=KEY_SIZE + FAIL_DESC_B + CONTENT_MIN_SIZE;
		if(size<minSize){
			l.error(ERROR_SIZE2);
			return false;
		}
		byte[] keyInbound=rdo.getKeyInbound();
		if(keyInbound!=null){
			if(keyInbound.length!=KEY_SIZE){
				l.error(ERROR_SIZE_KEY);
				return false;
			}
		}
		if(rdo.getParams()!=null)
			if(		(rdo.getParams().length>=rdo.getContent().length) 	|| 
					(rdo.getParams().length<=NUM_PAR_B+PAR_B)){
				l.error(ERROR_SIZE_PAR);
				return false;
			}
		//l.info("SizeControl--packetSize ok");
		return true;
	}
	
	
	private boolean fieldsSize(EventInfo ei) {
		DataObject rdo=ei.getDataObject();
		byte[] timestampB=rdo.getTimestamp();
		byte[] sessionB=rdo.getSession();
		if(		(timestampB.length==TIME_B)  	&&
				(sessionB.length==SESS_B)){
			try{
				long timestamp=ByteBuffer.wrap(timestampB).getLong();
				String session=new String(sessionB);
				if(		(timestamp>0)  				&&
						(session.length()>0)){
						byte[] seqNumberB=rdo.getSeqNumber();
						byte[] usernameB=rdo.getUsername();
						byte[] passwordB=rdo.getPassword();
						byte[] applUrlB=rdo.getAppLURL();
						byte[] wsNamespaceB=rdo.getWSNamespace();
						byte[] operationB=rdo.getOperation();

						if(		(seqNumberB.length>0)			&&
								(usernameB.length>0)			&&
								(passwordB.length>0)			&&
								(applUrlB.length>0)				&&
								(wsNamespaceB.length>0)			&&
								(operationB.length>0)
						){	
							long seqNumber=Long.parseLong(new String(seqNumberB));
							String username=new String(usernameB);
							String password=new String(passwordB);
							String applUrl=new String(applUrlB);
							String wsNamespace=new String(wsNamespaceB);
							String operation=new String(operationB);
							if(		(timestamp>0)  				&&
									(seqNumber>0)				&&
									(session.length()>0)		&&
									(username.length()>0)		&&
									(password.length()>0)		&&
									(applUrl.length()>0)		&&
									(wsNamespace.length()>0)	&&
									(operation.length()>0)
							){
							//	l.info("SizeControl--fieldsSize ok");
							}

						}else{
							l.error(ERROR_SIZE_FIELD);
							return false;}
					return true;
				}

			}catch(NumberFormatException e){
				l.error(ERROR_FORMAT_TIMESTAMP+ "\n"+e.getMessage());
				return false;
			}

		}
		l.error(ERROR_SIZE_FIELD2);
		return false;
	}
	
	
	
}
